// Copyright (c) 2025, 大连理工大学 (Dalian University of Technology)
//
// Licensed under the Mulan PSL v2.
// You can use this file according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of the License at
//
//     http://license.coscl.org.cn/MulanPSL2
//
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. SEE THE MULAN PSL v2
// FOR MORE DETAILS.

/*
 * @Author: qiulin_JXGM ql1746365080@gmail.com
 * @Date: 2024-09-03 11:02:22
 * @LastEditors: qiulin 1746365080@qq.com
 * @LastEditTime: 2024-12-23 14:56:57
 * @FilePath: \SGFEM\Import\BDFImport\BulkData\Property\PBEAMLParser.cpp
 */

#include "PBEAMLParser.h"

#include <algorithm>
#include <cstdint>

#include <boost/algorithm/string.hpp>

#include "Utility/Logging/SGLogger.h"

#include "DBManager/DBServiceFactory.h"
#include "DBManager/IService/Input/Property/IPBEAMLService.h"

#include "Import/BDFImport/BDFParserBase.h"

BULKDATA_ENTRY_PARSER_REG (PBEAML);

using namespace SG::DBManager;
using namespace SG::Import;
using namespace SG::DataStructure;
/*
// file://./../../Doc/MarkDown/BulkData/PBEAML/PBEAML.md>
*/
namespace
{
    std::map<SG::DataStructure::FEM::BeamSectionStandardTypes, size_t> DimSizeMap = {
        { SG::DataStructure::FEM::BeamSectionStandardTypes::BEAMSECTYPE_ROD, 1 },
        { SG::DataStructure::FEM::BeamSectionStandardTypes::BEAMSECTYPE_BAR, 2 },
        { SG::DataStructure::FEM::BeamSectionStandardTypes::BEAMSECTYPE_TUBE, 2 },
        { SG::DataStructure::FEM::BeamSectionStandardTypes::BEAMSECTYPE_TUBE2, 2 },
        { SG::DataStructure::FEM::BeamSectionStandardTypes::BEAMSECTYPE_BOX, 4 },
        { SG::DataStructure::FEM::BeamSectionStandardTypes::BEAMSECTYPE_BOX1, 6 },
        { SG::DataStructure::FEM::BeamSectionStandardTypes::BEAMSECTYPE_DBOX, 10 },
        { SG::DataStructure::FEM::BeamSectionStandardTypes::BEAMSECTYPE_I, 6 },
        { SG::DataStructure::FEM::BeamSectionStandardTypes::BEAMSECTYPE_I1, 4 },
        { SG::DataStructure::FEM::BeamSectionStandardTypes::BEAMSECTYPE_H, 4 },
        { SG::DataStructure::FEM::BeamSectionStandardTypes::BEAMSECTYPE_L, 4 },
        { SG::DataStructure::FEM::BeamSectionStandardTypes::BEAMSECTYPE_CHAN, 4 },
        { SG::DataStructure::FEM::BeamSectionStandardTypes::BEAMSECTYPE_CHAN1, 4 },
        { SG::DataStructure::FEM::BeamSectionStandardTypes::BEAMSECTYPE_CHAN2, 4 },
        { SG::DataStructure::FEM::BeamSectionStandardTypes::BEAMSECTYPE_T, 4 },
        { SG::DataStructure::FEM::BeamSectionStandardTypes::BEAMSECTYPE_T1, 4 },
        { SG::DataStructure::FEM::BeamSectionStandardTypes::BEAMSECTYPE_T2, 4 },
        { SG::DataStructure::FEM::BeamSectionStandardTypes::BEAMSECTYPE_CROSS, 4 },
        { SG::DataStructure::FEM::BeamSectionStandardTypes::BEAMSECTYPE_Z, 4 },
        { SG::DataStructure::FEM::BeamSectionStandardTypes::BEAMSECTYPE_HEXA, 3 },
        { SG::DataStructure::FEM::BeamSectionStandardTypes::BEAMSECTYPE_HAT, 4 },
        { SG::DataStructure::FEM::BeamSectionStandardTypes::BEAMSECTYPE_HAT1, 5 },
    };

}  // namespace

enum PBEAMLkey : std::uint8_t
{
    PBEAMLkey_PID   = 1,
    PBEAMLkey_MID   = 2,
    PBEAMLkey_GROUP = 3,
    PBEAMLkey_TYPE  = 4,
};

SG::DataStructure::Common::Status BDF::BULKDATA::ParsePBEAML (const std::shared_ptr<SG::DBManager::DBServiceFactory>& dbServiceFactory,
                                                              std::vector<std::string>&                               dividedEntryInfo)
{
    SG::DataStructure::FEM::PBEAMLData tempData;

    // 设置默认domainId为1
    tempData.m_domainId = 1;

    // 从分割后的词条中获取属性ID（PID）并赋值
    tempData.m_id = convertToI64 (dividedEntryInfo[PBEAMLkey_PID]);

    // 获取材料ID（MID）并赋值
    tempData.m_mId = convertToI64 (dividedEntryInfo[PBEAMLkey_MID]);

    // 获取截面组（GROUP），如果为空则设置默认值为"MSCBML0"
    std::string groupStr = dividedEntryInfo[PBEAMLkey_GROUP];
    boost::trim (groupStr);  // 去除字符串两边的空格
    if (groupStr.empty ())   // 如果GROUP字段为空，设置默认值
    {
        groupStr = "MSCBML0";
    }
    // 将GROUP字符串复制到tempData的m_group字段中
    std::strncpy (tempData.m_group, boost::algorithm::trim_copy (groupStr).c_str (), boost::algorithm::trim_copy (groupStr).size ());

    // 获取截面类型（TYPE）并赋值
    std::string typeStr = dividedEntryInfo[PBEAMLkey_TYPE];
    boost::trim (typeStr);  // 去除字符串两边的空格
    std::strncpy (tempData.m_type, boost::algorithm::trim_copy (typeStr).c_str (), boost::algorithm::trim_copy (typeStr).size ());

    // 根据截面类型计算所需的DIMi数量，使用tempData获取横截面类型
    size_t const dimSize = DimSizeMap[tempData.GetBeamSectionStandardTypes ()];

    size_t remainderDims = dimSize;  // 剩余待解析的截面参数数量
    // 1        剩余解析个数 dimSize
    //[2,-2]   剩余解析个数 dimSize+2
    //-1       剩余解析个数未知

    SG::DataStructure::FEM::PBEAMLData::section pbeamlSec;
    pbeamlSec.m_so    = 1.0;                   // 默认恢复应力为yes
    pbeamlSec.m_rdist = 0.0;
    pbeamlSec.m_dims.reserve (dimSize);        // 为截面尺寸分配空间
    tempData.m_section.push_back (pbeamlSec);  // 初始化section数据

    // 词条行数计算
    size_t const rowNum      = dividedEntryInfo.size () / 10;
    size_t       judgeRownum = rowNum - 1;
    int          lastindex   = findNonEmptyIndex (dividedEntryInfo, judgeRownum);  // 词条最后一个非空下标
    while (-1 == lastindex)
    {
        judgeRownum--;
        if (judgeRownum < 0)
        {
            throw std::runtime_error ("RBE2Parser: judgeRownum < 0");
        }
        lastindex = findNonEmptyIndex (dividedEntryInfo, judgeRownum);
    }

    // 逐行解析条目数据
    for (size_t curRow = 1; curRow < rowNum; curRow++)
    {
        for (size_t fieldsColumn = 1; fieldsColumn < 9; fieldsColumn++)
        {
            const size_t curIndex  = curRow * 10 + fieldsColumn;
            std::string& curStrKey = dividedEntryInfo[curIndex];

            // 检查当前字段是否为空白，如果为空则默认赋值为0
            bool const isEmpty = is_all_space (curStrKey);
            if (isEmpty)
            {
                curStrKey = "0";
            }

            // 处理不同参数类型，根据remainderDims的值来判断
            if (remainderDims == dimSize + 2)  // 处理SO字段（是否恢复应力）
            {
                boost::trim (curStrKey);
                if ("NO" == curStrKey)
                {
                    tempData.m_section.back ().m_so = 0.0;
                }
                else
                {
                    tempData.m_section.back ().m_so = 1.0;
                }
            }
            else if (remainderDims == dimSize + 1)  // 处理X(m)字段（位置）
            {
                tempData.m_section.back ().m_rdist = convertToReal (curStrKey);
            }
            else if (remainderDims == 0)                   // 处理NSM字段
            {
                tempData.m_section.back ().m_nsm = convertToReal (curStrKey);
                tempData.m_section.push_back (pbeamlSec);  // 重置section
                remainderDims = dimSize + 2;               // 重置remainderDims
                continue;                                  // 跳过递减
            }
            else                                           // 处理截面尺寸DIMi字段
            {
                tempData.m_section.back ().m_dims.push_back (convertToReal (curStrKey));
            }
            remainderDims--;

            // 如果处理到最后一个元素，跳出循环
            if (curIndex == static_cast<size_t> (lastindex))
            {
                break;
            }
        }
    }

    if (tempData.m_section.size () == 1)
    {
        tempData.m_section.push_back (tempData.m_section.front ());
    }

    // 处理最后一个截面
    tempData.m_section.back ().m_rdist = 1.0;

    // 补充截面尺寸，如果未填满则使用A端内容替代
    if (tempData.m_section.back ().m_dims.size () < dimSize)
    {
        tempData.m_section.back ().m_dims.resize (dimSize);
    }
    for (size_t i = 0; i < tempData.m_section.back ().m_dims.size (); i++)
    {
        if (tempData.m_section.back ().m_dims[i] == 0.0)
        {
            tempData.m_section.back ().m_dims[i] = tempData.m_section.front ().m_dims[i];
        }
    }

    // 若NSM为空，使用A端截面内容替代
    if (tempData.m_section.back ().m_nsm == 0.0)
    {
        tempData.m_section.back ().m_nsm = tempData.m_section.front ().m_nsm;
    }

    return dbServiceFactory->get<IPBEAMLService> ()->Add (tempData);  // 将数据添加到数据库
}